package com.ilearn.iodata.iolingo.service.processor;

import com.ilearn.iodata.iolingo.service.GetCollectionService;
import com.ilearn.iodata.iolingo.service.processor.core.api.GenericODataRequestContextAccess;
import com.ilearn.iodata.iolingo.service.processor.core.api.GenericODataSessionContextAccess;
import com.ilearn.iodata.iolingo.service.processor.core.exception.ODataGenericProcessorException;
import com.ilearn.iodata.iolingo.service.processor.core.processor.GenericAbstractGetRequestProcessor;
import com.ilearn.iodata.iolingo.service.processor.core.query.GenericJoinQuery;
import org.apache.olingo.commons.api.data.EntityCollection;
import org.apache.olingo.commons.api.edm.EdmEntitySet;
import org.apache.olingo.commons.api.ex.ODataException;
import org.apache.olingo.commons.api.format.ContentType;
import org.apache.olingo.commons.api.http.HttpStatusCode;
import org.apache.olingo.server.api.OData;
import org.apache.olingo.server.api.ODataRequest;
import org.apache.olingo.server.api.ODataResponse;
import org.apache.olingo.server.api.uri.UriInfo;
import org.apache.olingo.server.api.uri.UriResource;
import org.apache.olingo.server.api.uri.UriResourceEntitySet;
import org.apache.olingo.server.api.uri.UriResourceKind;

import java.util.List;

import static com.ilearn.iodata.iolingo.service.processor.core.exception.ODataGenericProcessorException.MessageKeys.QUERY_PREPARATION_ERROR;
import static org.apache.olingo.server.api.uri.UriResourceKind.entitySet;


public class GenericCountRequestProcessor extends GenericAbstractGetRequestProcessor {

    private GetCollectionService getCollectionService;

    public GenericCountRequestProcessor(final OData odata, final GenericODataSessionContextAccess context,
                                        final GenericODataRequestContextAccess requestContext,
                                        GetCollectionService getCollectionService) throws ODataException {
        super(odata, context, requestContext);
        this.getCollectionService = getCollectionService;
    }

    @Override
    public void retrieveData(final ODataRequest request, final ODataResponse response, final ContentType responseFormat)
            throws ODataException {
        final UriResource uriResource = uriInfo.getUriResourceParts().get(0);

        if (uriResource instanceof UriResourceEntitySet) {
            UriResourceEntitySet uriResourceEntitySet = (UriResourceEntitySet) uriResource;
            EdmEntitySet edmEntitySet = uriResourceEntitySet.getEntitySet();
            final EntityCollection result = countEntities(request, response, uriInfo, edmEntitySet);
            createSuccessResponce(response, ContentType.TEXT_PLAIN, serializer.serialize(request, result));
        } else {
            throw new ODataGenericProcessorException(ODataGenericProcessorException.MessageKeys.NOT_SUPPORTED_RESOURCE_TYPE,
                    HttpStatusCode.NOT_IMPLEMENTED, uriResource.getKind().toString());
        }
    }

    protected final EntityCollection countEntities(final ODataRequest request, final ODataResponse response,
                                                   final UriInfo uriInfo, EdmEntitySet edmEntitySet) throws ODataException {

        GenericJoinQuery query = null;

        try {
            query = new GenericJoinQuery(odata, uriInfo, edmEntitySet , null);
        } catch (ODataException e) {
            throw new ODataGenericProcessorException(QUERY_PREPARATION_ERROR, HttpStatusCode.INTERNAL_SERVER_ERROR, e);
        }

        GenericJoinQuery.EntityCount entityCount = query.fetchEntityCount(getCollectionService);

        final EntityCollection entityCollection = new EntityCollection();

        if (entityCount != null) {
            entityCollection.setCount(entityCount.getCount());
        }
        return entityCollection;
    }
}
